package com.cloudkinto.service.tailtrucks.impl;

import cn.afterturn.easypoi.entity.ImageEntity;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.excel.export.styler.ExcelExportStylerDefaultImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.DicBusinessConstant;
import com.cloudkinto.common.DicBusinessItemConstant;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelExportStylerBorderImpl;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.OrderCodeUtil;
import com.cloudkinto.common.utils.TimeUtils;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.company.CompanyService;
import com.cloudkinto.service.dic.LanguageCountEntity;
import com.cloudkinto.service.dic.vo.LanguageValueEntity;
import com.cloudkinto.service.fbaorderoutput.FbaOrderOutputService;
import com.cloudkinto.service.fbaorderoutput.vo.FbaOrderOutputCommonExportVo;
import com.cloudkinto.service.fbaorderoutput.vo.FbaOrderOutputCommonPackageExportVo;
import com.cloudkinto.service.fbaorderoutput.vo.FbaOrderOutputCommonProductExportVo;
import com.cloudkinto.service.fbaorderoutput.vo.FbaOrderOutputUploadFileReq;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.finance.vo.IdAndNameEntity;
import com.cloudkinto.service.firstvesselorder.FirstVesselOrderService;
import com.cloudkinto.service.shop.ShopService;
import com.cloudkinto.service.storage.FbaStorageService;
import com.cloudkinto.service.storage.StorageService;
import com.cloudkinto.service.storage.vo.StorageListRes;
import com.cloudkinto.service.tailtrucks.TailTrucksService;
import com.cloudkinto.service.tailtrucks.vo.*;
import com.cloudkinto.utils.BarCodeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author zhangyy
 * @since 2020-10-28
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class TailTrucksServiceImpl extends ServiceImpl<TailTrucksDao, TailTrucksDo> implements TailTrucksService {
    @Autowired
    private TailTrucksDao dao;
    @Autowired
    private FbaStorageService fbaStorageService;
    @Autowired
    private TrucksTemplateDao trucksTemplateDao;
    @Autowired
    private TailTrucksDetailDao tailTrucksDetailDao;
    @Autowired
    private TailTrucksAmazonTimeDao tailTrucksAmazonTimeDao;
    @Autowired
    private FirstVesselOrderPackageDao firstVesselOrderPackageDao;
    @Autowired
    private FirstVesselOrderService firstVesselOrderService;
    @Autowired
    private FbaOrderOutputService fbaOrderOutputService;
    @Autowired
    private FbaOrderOutputDao orderOutputDao;
    @Autowired
    private FbaOrderOutputPackageDao orderOutputPackageDao;
    @Autowired
    private FbaOrderOutputProductDao orderOutputProductDao;
    @Autowired
    private FirstVesselOrderProductDao firstVesselOrderProductDao;
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private FbaStorageDao fbaStorageDao;
    @Autowired
    private DicBusinessItemDao dicBusinessItemDao;
    @Autowired
    private StorageService storageService;
    @Autowired
    private StorageDao storageDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private FileService fileService;

    //真正的存储路径
    @Value("${gbc.uploadPath.filePathLocal}")
    private String filePathLocal;
    //真正的存储路径
    @Value("${gbc.template.filePath}")
    private String templatePath;
    @Autowired
    private FbaOrderOutputDao fbaOrderOutputDao;
    @Autowired
    private FbaOrderOutputPackageDao fbaOrderOutputPackageDao;
    @Autowired
    private FbaOrderOutputProductDao fbaOrderOutputProductDao;
    @Autowired
    private ThreadPoolTaskExecutor executor;
    @Autowired
    private MailDao mailDao;
    @Autowired
    private ShopService shopService;
    @Autowired
    private CompanyService companyService;


    @Override
    public SingleResult addInit() {
        Map result = new HashMap();

        result.put("fbaStorageList", fbaStorageService.getStorageList());
        result.put("statusList", getStatusList());


        List<Map> trucksTemplateList = new ArrayList<>();
        List<TrucksTemplateDo> trucksTemplateDos = trucksTemplateDao.selectList(null);
        if (!CollectionUtils.isEmpty(trucksTemplateDos)) {
            trucksTemplateDos.forEach(trucksTemplateDo -> {
                Map map = new HashMap();
                map.put("id", trucksTemplateDo.getId());
                map.put("value", trucksTemplateDo.getTrucksCode());
                map.put("storageId", trucksTemplateDo.getStorageId());
                map.put("volume", trucksTemplateDo.getVolume());
                map.put("weight", trucksTemplateDo.getWeight());
                trucksTemplateList.add(map);
            });
        }
        result.put("trucksTemplateList", trucksTemplateList);

        Map<String, String> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("countryType", "1");
        List<StorageListRes> storageList = storageService.getList(objectObjectHashMap);
        result.put("storageList", storageList);

        return SingleResult.success(result);
    }

    private List<LanguageValueEntity> getStatusList() {
        List<LanguageValueEntity> mapList = new ArrayList<>();
        mapList.add(new LanguageValueEntity(1, "待确定"));
        mapList.add(new LanguageValueEntity(5, "待回复"));
        mapList.add(new LanguageValueEntity(2, "待约车"));
        mapList.add(new LanguageValueEntity(3, "已约车"));
        mapList.add(new LanguageValueEntity(4, "已配送"));

        return mapList;
    }

    @Override
    public void add(TailTrucksAddReq req, Long userId) {
        addCheck(req);
        TailTrucksDo entityDo = new TailTrucksDo();
        BeanUtils.copyProperties(req, entityDo);
        entityDo.setStatus(1);
        entityDo.setTrucksId(req.getTrucksTempId());
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        entityDo.setCreateBy(userId);
        entityDo.setCreateTime(new Date());
        dao.insert(entityDo);
        String tailTrucksNumber = OrderCodeUtil.getTailTrucksNumber(entityDo.getId());
        entityDo.setTrucksNumber(tailTrucksNumber);
        dao.updateById(entityDo);
    }

    private void addCheck(TailTrucksAddReq req) {
        TrucksTemplateDo trucksTemplateDo = trucksTemplateDao.selectById(req.getTrucksTempId());
        if (trucksTemplateDo != null) {
            if (!req.getStorageId().equals(trucksTemplateDo.getStorageId())) {
                if (req.getStorageId() == 1 || trucksTemplateDo.getStorageId() == 10) {
                } else if (req.getStorageId() == 10 || trucksTemplateDo.getStorageId() == 1) {
                } else if (req.getStorageId() == 10 || trucksTemplateDo.getStorageId() == 11) {
                } else if (req.getStorageId() == 11 || trucksTemplateDo.getStorageId() == 10) {
                } else {
                    throw new BizException(SysConstant.TailTrucks_Check_Storage_Error);
                }
            }
        }
    }

    /**
     * 亚马逊ID
     *
     * @param req
     * @param userId
     */
    @Override
    public void amazonTime(TailTrucksConTimeReq req, Long userId) {
        if (StringUtils.isBlank(req.getAppointmentCode()) && StringUtils.isBlank(req.getAppointmentCode2()) && StringUtils.isBlank(req.getAppointmentCode3())) {
            throw new BizException(SysConstant.TailTrucks_Fill_Code);
        }
        TailTrucksDo tailTrucksDo = dao.selectById(req.getId());
        if (tailTrucksDo == null) {
            throw new BizException(SysConstant.Error_Data_NotExist);
        }
        if (tailTrucksDo.getStatus() == 4) {
            throw new BizException(SysConstant.TailTrucks_Code_Error);
        }
        if (StringUtils.isNotBlank(req.getAppointmentCode().trim())) {
            tailTrucksDo.setAppointmentCode(req.getAppointmentCode());

            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode2()) && tailTrucksDo.getAppointmentCode2().equals(tailTrucksDo.getAppointmentCode())) {
                throw new BizException(SysConstant.TailTrucks_Code_Repeat);
            }
            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode3()) && tailTrucksDo.getAppointmentCode3().equals(tailTrucksDo.getAppointmentCode())) {
                throw new BizException(SysConstant.TailTrucks_Code_Repeat);
            }
        }
        if (StringUtils.isNotBlank(req.getAppointmentCode2().trim())) {
            tailTrucksDo.setAppointmentCode2(req.getAppointmentCode2());

            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode()) && tailTrucksDo.getAppointmentCode().equals(tailTrucksDo.getAppointmentCode2())) {
                throw new BizException(SysConstant.TailTrucks_Code_Repeat);
            }
            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode3()) && tailTrucksDo.getAppointmentCode3().equals(tailTrucksDo.getAppointmentCode2())) {
                throw new BizException(SysConstant.TailTrucks_Code_Repeat);
            }
        }
        if (StringUtils.isNotBlank(req.getAppointmentCode3().trim())) {
            tailTrucksDo.setAppointmentCode3(req.getAppointmentCode3());

            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode2()) && tailTrucksDo.getAppointmentCode2().equals(tailTrucksDo.getAppointmentCode3())) {
                throw new BizException(SysConstant.TailTrucks_Code_Repeat);
            }
            if (StringUtils.isNotBlank(tailTrucksDo.getAppointmentCode()) && tailTrucksDo.getAppointmentCode().equals(tailTrucksDo.getAppointmentCode3())) {
                throw new BizException(SysConstant.TailTrucks_Code_Repeat);
            }
        }

        //只有状态 是 待确定 才状态改成待回复
        if (tailTrucksDo.getStatus() == 1) {
            tailTrucksDo.setStatus(5);
        }
        dao.updateById(tailTrucksDo);

        LambdaUpdateWrapper<TailTrucksDo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TailTrucksDo::getId, tailTrucksDo.getId());
        boolean flag = false;

        if (StringUtils.isNotBlank(req.getAppointmentCode().trim())) {
            TailTrucksAmazonTimeDo timeDo = tailTrucksAmazonTimeDao.selectOne(new LambdaQueryWrapper<TailTrucksAmazonTimeDo>()
                    .eq(TailTrucksAmazonTimeDo::getAppointmentCode, req.getAppointmentCode().trim()).last(" order by id desc limit 1"));
            if (timeDo != null) {
                MailDo mailDo = mailDao.selectById(timeDo.getMailId());
                if (mailDo != null) {
                    Date amazonTime = this.getAmazonTimeByMail(mailDo.getSubject());
                    updateWrapper.set(TailTrucksDo::getAmazonTime, amazonTime);

                    if (tailTrucksDo.getAmazonTime() != null && (amazonTime == null || tailTrucksDo.getAmazonTime().getTime() != amazonTime.getTime())) {
                        updateWrapper.set(TailTrucksDo::getTimeStatus, "unnormal");
                    }
                    if (amazonTime != null && tailTrucksDo.getStatus() == 5) {
                        updateWrapper.set(TailTrucksDo::getStatus, 2);
                    }
                    flag = true;
                }
            }

        }

        if (StringUtils.isNotBlank(req.getAppointmentCode2().trim())) {
            TailTrucksAmazonTimeDo timeDo = tailTrucksAmazonTimeDao.selectOne(new LambdaQueryWrapper<TailTrucksAmazonTimeDo>()
                    .eq(TailTrucksAmazonTimeDo::getAppointmentCode, req.getAppointmentCode2().trim()).last(" order by id desc limit 1"));
            if (timeDo != null) {
                MailDo mailDo = mailDao.selectById(timeDo.getMailId());
                if (mailDo != null) {
                    Date amazonTime = this.getAmazonTimeByMail(mailDo.getSubject());
                    updateWrapper.set(TailTrucksDo::getAmazonTime2, amazonTime);

                    if (tailTrucksDo.getAmazonTime2() != null && (amazonTime == null || tailTrucksDo.getAmazonTime2().getTime() != amazonTime.getTime())) {
                        updateWrapper.set(TailTrucksDo::getTimeStatus2, "unnormal");
                    }
                    if (amazonTime != null && tailTrucksDo.getStatus() == 5) {
                        updateWrapper.set(TailTrucksDo::getStatus, 2);
                    }
                    flag = true;
                }
            }
        }
        if (StringUtils.isNotBlank(req.getAppointmentCode3().trim())) {
            TailTrucksAmazonTimeDo timeDo = tailTrucksAmazonTimeDao.selectOne(new LambdaQueryWrapper<TailTrucksAmazonTimeDo>()
                    .eq(TailTrucksAmazonTimeDo::getAppointmentCode, req.getAppointmentCode3().trim()).last(" order by id desc limit 1"));
            if (timeDo != null) {
                MailDo mailDo = mailDao.selectById(timeDo.getMailId());
                if (mailDo != null) {
                    Date amazonTime = this.getAmazonTimeByMail(mailDo.getSubject());
                    updateWrapper.set(TailTrucksDo::getAmazonTime3, amazonTime);

                    //如果柜子 有亚马逊时间 ，且匹配后消除了 或者变更了亚马逊约车时间 就要把状态变成 unnormal
                    if (tailTrucksDo.getAmazonTime3() != null && (amazonTime == null || tailTrucksDo.getAmazonTime3().getTime() != amazonTime.getTime())) {
                        updateWrapper.set(TailTrucksDo::getTimeStatus3, "unnormal");
                    }
                    //如果 有亚马逊约车时间，且 他的状态是 待回复(5) 就要变成 待约车(2)
                    if (amazonTime != null && tailTrucksDo.getStatus() == 5) {
                        updateWrapper.set(TailTrucksDo::getStatus, 2);
                    }
                    flag = true;
                }
            }
        }
        if (flag) {
            this.update(updateWrapper);
        }

    }

    /**
     * 根基邮件主题 获取亚马逊时间
     *
     * @param subject
     * @return
     */
    @Override
    public Date getAmazonTimeByMail(String subject) {
        String amazonTime = null;
        if (subject.contains("削除")) {
            //亚马逊确认时间消除
            return null;
        } else if (subject.contains("搬入指定日時変更") || subject.contains("アポイントメントID ")) {
            //日期变更
            amazonTime = subject.substring(subject.indexOf(" 、搬入指定日時 ") + " 、搬入指定日時 ".length(), subject.indexOf(" 、搬入指定日時 ") + 17 + " 、搬入指定日時 ".length()).trim();
            if (amazonTime == null) {
                log.error(String.format("该FBA邮件未找到时间格式:%s", subject));
                return null;
            }
            return DateUtils.stringFormatToDateHms(amazonTime, "yyyy/MM/dd HH:mm");
        } else if (subject.contains("Appointment Time")) {
            //Fri 02/17/2023 10:00
            amazonTime = subject.substring(subject.indexOf("Time:") + "Time:".length(), subject.indexOf("JST")).trim();
            if (amazonTime == null) {
                log.error(String.format("该FBA邮件未找到时间格式:%s", subject));
                return null;
            }
            return DateUtils.stringFormatToDateHms(amazonTime, "EEE MM/dd/yyyy HH:mm");
        }

        return null;
    }


    @Override
    public String getAppointmentCodeByMail(String subject) {
        String appointmentCode = null;
        if (subject.contains("削除")) {
            //亚马逊确认时间消除
            appointmentCode = subject.substring(subject.indexOf(":") + 2).trim();
        } else if (subject.contains("搬入指定日時変更")) {
            //日期变更
            appointmentCode = subject.substring(subject.indexOf("アポイントメントID #") + "アポイントメントID #".length(), subject.indexOf(" 、搬入指定日時 ")).trim();
        } else if (subject.contains("アポイントメントID ")) {
            //指定日期
            appointmentCode = subject.substring(subject.indexOf("アポイントメントID ") + "アポイントメントID ".length(), subject.indexOf(" 、搬入指定日時")).trim();
        }
        return appointmentCode;
    }

    @Override
    public void trucksAppointment(TailTrucksAppointmentReq req, Long userId) {
        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(req.getId());
        tailTrucksDo.setAppointmentTime(TimeUtils.parseDate(req.getAppointmentTime(), "yyyy-MM-dd HH:mm"));
        tailTrucksDo.setTrucksId(req.getTrucksId());
        this.baseMapper.updateById(tailTrucksDo);
        TailTrucksUpdateStatusReq statusReq = new TailTrucksUpdateStatusReq();
        statusReq.setId(req.getId());
        statusReq.setStatus(3);
        updateStatus(statusReq, userId);
    }

    @Override
    public void autoTrucksAppointment(List<Long> ids) {
        for (Long id : ids) {
            //已经约车的 不进行约车
            LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TailTrucksDetailDo::getTrucksId, id);
            int count = tailTrucksDetailDao.selectCount(wrapper);
            if (count > 0) {
                continue;
            }
            handlerTrucks(id);
        }
    }

    private void handlerTrucks(Long id) {
        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(id);
        TrucksTemplateDo trucksTemplateDo = trucksTemplateDao.selectById(tailTrucksDo.getTrucksId());

        List<Long> vesselOrderIds = new ArrayList<>();
        boolean vesselFlag = false;
        List<Long> outOrderIds = new ArrayList<>();
        boolean outFlag = false;
        double volume = 0;
        double weight = 0;


        //该算法是 先算头程 如果头程订单拼接完了还有剩余 则 转运的不进行拼接  如果没有拼接玩 继续 拼转运的
        LambdaQueryWrapper<FirstVesselOrderDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FirstVesselOrderDo::getIsContainer, SysConstant.DELETE_FLAG_FALSE)
                .eq(FirstVesselOrderDo::getStorageId, tailTrucksDo.getStorageId())
                .eq(FirstVesselOrderDo::getFbaStorageId, tailTrucksDo.getFbaStorageId());
        List<FirstVesselOrderDo> firstVesselOrderDos = firstVesselOrderService.getBaseMapper().selectList(wrapper);
        if (!CollectionUtils.isEmpty(firstVesselOrderDos)) {
            for (FirstVesselOrderDo firstVesselOrderDo : firstVesselOrderDos) {
                LambdaQueryWrapper<FirstVesselOrderPackageDo> packageWrapper = new LambdaQueryWrapper<>();
                packageWrapper.eq(FirstVesselOrderPackageDo::getOrderId, firstVesselOrderDo.getId());
                List<FirstVesselOrderPackageDo> firstVesselOrderPackageDos = firstVesselOrderPackageDao.selectList(packageWrapper);
                if (!CollectionUtils.isEmpty(firstVesselOrderPackageDos)) {
                    for (FirstVesselOrderPackageDo firstVesselOrderPackageDo : firstVesselOrderPackageDos) {
                        volume += firstVesselOrderPackageDo.getCount() * firstVesselOrderPackageDo.getLength() * firstVesselOrderPackageDo.getHeight() * firstVesselOrderPackageDo.getWidth() / 1000000;
                        weight += firstVesselOrderPackageDo.getWeight();

                        if (trucksTemplateDo.getVolume() < volume || trucksTemplateDo.getWeight() < weight) {
                            vesselFlag = true;
                            break;
                        }
                    }
                }
                if (vesselFlag) {
                    break;
                }
                vesselOrderIds.add(firstVesselOrderDo.getId());
            }
        }
        TailTrucksJointTrucksReq req = new TailTrucksJointTrucksReq();
        req.setId(id);
        req.setOrderIds(vesselOrderIds);
        req.setType(1);
        jointTrucks(req, false);

        LambdaQueryWrapper<FbaOrderOutputDo> outputWrapper = new LambdaQueryWrapper<>();
        outputWrapper.eq(FbaOrderOutputDo::getIsTrucks, SysConstant.DELETE_FLAG_FALSE)
                .eq(FbaOrderOutputDo::getStorageId, tailTrucksDo.getStorageId())
                .eq(FbaOrderOutputDo::getFbaStorageId, tailTrucksDo.getFbaStorageId());
        List<FbaOrderOutputDo> orderOutputDos = fbaOrderOutputService.getBaseMapper().selectList(outputWrapper);
        if (!CollectionUtils.isEmpty(orderOutputDos)) {
            for (FbaOrderOutputDo orderOutputDo : orderOutputDos) {
                LambdaQueryWrapper<FbaOrderOutputPackageDo> packageDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                packageDoLambdaQueryWrapper.eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, orderOutputDo.getId());
                List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(packageDoLambdaQueryWrapper);
                if (!CollectionUtils.isEmpty(packageDoList)) {
                    for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                        volume += packageDo.getCount() * packageDo.getLength() * packageDo.getHeight() * packageDo.getWidth() / 1000000;
                        weight += packageDo.getWeight();
                        //todo
                        if (trucksTemplateDo.getVolume() < volume || trucksTemplateDo.getWeight() < weight) {
                            outFlag = true;
                            break;
                        }
                    }
                }
                if (outFlag) {
                    break;
                }
                outOrderIds.add(orderOutputDo.getId());
            }
        }
        TailTrucksJointTrucksReq req2 = new TailTrucksJointTrucksReq();
        req2.setId(id);
        req2.setOrderIds(outOrderIds);
        req2.setType(2);
        jointTrucks(req2, false);
    }

    @Override
    public SingleResult updateStatusInit() {
        List<LanguageValueEntity> mapList = new ArrayList<>();
        mapList.add(new LanguageValueEntity(1, "待确定"));
        mapList.add(new LanguageValueEntity(2, "待约车"));
        mapList.add(new LanguageValueEntity(3, "已约车"));
        mapList.add(new LanguageValueEntity(4, "已配送"));
        return SingleResult.success(mapList);
    }

    @Override
    public void updateStatus(TailTrucksUpdateStatusReq req, Long userId) {
        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(req.getId());
        tailTrucksDo.setStatus(req.getStatus());
        this.baseMapper.updateById(tailTrucksDo);

        handlerOrderStatus(req, userId);
    }

    @Override
    public void uploadSignatureFile(FbaOrderOutputUploadFileReq req) {
        LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TailTrucksDetailDo::getType, 2).eq(TailTrucksDetailDo::getTrucksId, req.getId());
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(wrapper);
        if (CollectionUtils.isEmpty(tailTrucksDetailDos)) return;
        for (TailTrucksDetailDo tailTrucksDetailDo : tailTrucksDetailDos) {
            FbaOrderOutputDo fbaOrderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
            fileService.deleteFile(fbaOrderOutputDo.getSignatureFileId());
            fileService.uploadFile2(req.getFileId(), fbaOrderOutputDo.getFileId());
            fbaOrderOutputDo.setSignatureFileId(req.getFileId());
            fbaOrderOutputService.getBaseMapper().updateById(fbaOrderOutputDo);
        }
    }

    private void handlerOrderStatus(TailTrucksUpdateStatusReq req, Long userId) {
        LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TailTrucksDetailDo::getTrucksId, req.getId()).eq(TailTrucksDetailDo::getType, 2);
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(tailTrucksDetailDos)) {
            for (TailTrucksDetailDo tailTrucksDetailDo : tailTrucksDetailDos) {
                FbaOrderOutputDo fbaOrderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                if (fbaOrderOutputDo != null) {
                    if (req.getStatus() == 1) {
                        fbaOrderOutputDo.setStatus(DicBusinessItemConstant.fbaInCreateState);
                    } else if (req.getStatus() == 2) {
                        fbaOrderOutputDo.setStatus(DicBusinessItemConstant.fbaOrderAppointStorageStatus);
                    } else if (req.getStatus() == 3) {
                        fbaOrderOutputDo.setStatus(DicBusinessItemConstant.fbaOrderAppointCarStatus);
                    } else if (req.getStatus() == 4) {
                        if (fbaOrderOutputDo.getStatus() < DicBusinessItemConstant.fbaOrderSendOutStatus
                                || fbaOrderOutputDo.getStatus() == DicBusinessItemConstant.fbaOrderProblemStatus) {
                            fbaOrderOutputService.dealwithOrderSendOut(fbaOrderOutputDo, fbaOrderOutputDo.getTrackId(), userId);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void jointTrucks(TailTrucksJointTrucksReq req, boolean flag) {
        if (CollectionUtils.isEmpty(req.getOrderIds())) return;
        //校验是否超标
//        if (flag) {
//            jointTrucksCheck(req);
//        }

        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(req.getId());
        //处理从表信息 以及 更新 first_vessel_order表 is_container状态
        handlerInsertTailTrucksDetail(req.getOrderIds(), tailTrucksDo, req.getType());

        //更新主表信息
        updateTrucksInfo(req.getId());

    }


    @Override
    public void jointFbaTrucks(TailTrucksJointFbaReq req, Long userId) {
        jointCheck(req);

        //获取所有订单的信息
        TailTrucksOrderInfo orderInfo = getOrderInfo(req.getIds());
        LambdaQueryWrapper<TailTrucksDo> tailListWrapper = new LambdaQueryWrapper<>();
        if (orderInfo.getStorageId() == 10 || orderInfo.getStorageId() == 1 || orderInfo.getStorageId() == 11) {
            tailListWrapper.and(new Consumer<LambdaQueryWrapper<TailTrucksDo>>() {
                @Override
                public void accept(LambdaQueryWrapper<TailTrucksDo> tailTrucksDoLambdaQueryWrapper) {
                    tailTrucksDoLambdaQueryWrapper.or().eq(TailTrucksDo::getStorageId, 1)
                            .or().eq(TailTrucksDo::getStorageId, 11)
                            .or().eq(TailTrucksDo::getStorageId, 10);
                }
            });
        } else {
            tailListWrapper.eq(TailTrucksDo::getStorageId, orderInfo.getStorageId());
        }
        tailListWrapper.eq(TailTrucksDo::getFbaStorageId, orderInfo.getFbaStorageId())
                .eq(TailTrucksDo::getStatus, DicBusinessItemConstant.tailtruckInCreateState);
        int integer = dao.selectCount(tailListWrapper);
        if (integer > 0) {
            List<TailTrucksDo> trucksDoList = dao.selectList(tailListWrapper);
            double maxRate = 0;
            TailTrucksDo tailTrucksDoTemp = null;
            for (TailTrucksDo tailTrucksDo : trucksDoList) {
                TrucksTemplateDo trucksTemplateDo = trucksTemplateDao.selectById(tailTrucksDo.getTrucksId());
                double bothMax = 0;
                double volume = orderInfo.getTotalVolume() / trucksTemplateDo.getVolume();
                double weight = orderInfo.getTotalWeight() / trucksTemplateDo.getWeight();
                bothMax = weight > volume ? weight : volume;
                if (maxRate < bothMax) {
                    maxRate = bothMax;
                    tailTrucksDoTemp = tailTrucksDo;
                }
            }
            if (tailTrucksDoTemp == null) {
                for (TailTrucksDo tailTrucksDo : trucksDoList) {
                    TrucksTemplateDo trucksTemplateDo = trucksTemplateDao.selectById(tailTrucksDo);
                    LambdaQueryWrapper<TrucksTemplateDo> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(TrucksTemplateDo::getStorageId, orderInfo.getStorageId());
                    wrapper.gt(TrucksTemplateDo::getVolume, trucksTemplateDo.getVolume());
                    wrapper.gt(TrucksTemplateDo::getWeight, trucksTemplateDo.getWeight());
                    wrapper.orderByAsc(TrucksTemplateDo::getVolume);
                    List<TrucksTemplateDo> trucksTemplateDos = trucksTemplateDao.selectList(wrapper);
                    if (trucksTemplateDos == null || trucksTemplateDos.size() < 1) continue;
                    trucksTemplateDo = trucksTemplateDos.get(0);
                    double bothMax = 0;
                    double volume = orderInfo.getTotalVolume() / trucksTemplateDo.getVolume();
                    double weight = orderInfo.getTotalWeight() / trucksTemplateDo.getWeight();
                    bothMax = weight > volume ? weight : volume;
                    if (maxRate < bothMax) {
                        maxRate = bothMax;
                        tailTrucksDoTemp = tailTrucksDo;
                    }
                }
            }
            if (tailTrucksDoTemp == null) return;
            tailTrucksDoTemp.setProductCount(tailTrucksDoTemp.getProductCount() + orderInfo.getProductCount());
            tailTrucksDoTemp.setPackageCount(tailTrucksDoTemp.getPackageCount() + orderInfo.getPackageCount());
            tailTrucksDoTemp.setTotalVolume(tailTrucksDoTemp.getTotalVolume() + orderInfo.getTotalVolume());
            tailTrucksDoTemp.setTotalWeight(tailTrucksDoTemp.getTotalWeight() + orderInfo.getTotalWeight());
            updateById(tailTrucksDoTemp);
            //插入从表信息
            handlerInsertTailTrucksDetail(req.getIds(), tailTrucksDoTemp, 2);
            return;
        }
        LambdaQueryWrapper<TrucksTemplateDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrucksTemplateDo::getStorageId, orderInfo.getStorageId());
        List<TrucksTemplateDo> trucksTemplateDos = trucksTemplateDao.selectList(wrapper);
        if (CollectionUtils.isEmpty(trucksTemplateDos)) {
            throw new BizException(SysConstant.TailTrucks_JoinTrucks_Error);
        }
        List<TrucksTemplateDo> trucksTemplateDoList = trucksTemplateDos.stream().sorted(Comparator.comparing(TrucksTemplateDo::getVolume)).sorted(Comparator.comparing(TrucksTemplateDo::getWeight)).collect(Collectors.toList());

        Long templateId = null;
        for (int i = 0; i < trucksTemplateDoList.size(); i++) {
            if ((orderInfo.getTotalVolume() <= trucksTemplateDoList.get(i).getVolume() && orderInfo.getTotalWeight() <= trucksTemplateDoList.get(i).getWeight()) || i == trucksTemplateDoList.size() - 1) {
                templateId = trucksTemplateDoList.get(i).getId();
                break;
            }
        }
        //插入约车主表信息
        TailTrucksDo tailTrucksDo = handlerInsertTailTrucksDo(orderInfo, templateId, userId);

        //插入从表信息
        handlerInsertTailTrucksDetail(req.getIds(), tailTrucksDo, 2);

    }

    @Override
    public SingleResult fbaOrderSingleJointInit(Long id) {
        List<TailTrucksPageRes> res = new ArrayList<>();
        FbaOrderOutputDo fbaOrderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(id);
        if (fbaOrderOutputDo.getIsTrucks() == 1) {
            throw new BizException(SysConstant.TailTrucks_JonInit_Error);
        }
        LambdaQueryWrapper<TailTrucksDo> wrapper = new LambdaQueryWrapper<>();
        if (fbaOrderOutputDo.getStorageId() == 10 || fbaOrderOutputDo.getStorageId() == 1 || fbaOrderOutputDo.getStorageId() == 11) {
            wrapper.and(new Consumer<LambdaQueryWrapper<TailTrucksDo>>() {
                @Override
                public void accept(LambdaQueryWrapper<TailTrucksDo> tailTrucksDoLambdaQueryWrapper) {
                    tailTrucksDoLambdaQueryWrapper.or().eq(TailTrucksDo::getStorageId, 1)
                            .or().eq(TailTrucksDo::getStorageId, 11)
                            .or()
                            .eq(TailTrucksDo::getStorageId, 10);
                }
            });
        } else {
            wrapper.eq(TailTrucksDo::getStorageId, fbaOrderOutputDo.getStorageId());
        }
        wrapper.lt(TailTrucksDo::getStatus, DicBusinessItemConstant.tailtruckSendOutStatus)
                .eq(TailTrucksDo::getFbaStorageId, fbaOrderOutputDo.getFbaStorageId());
        List<TailTrucksDo> tailTrucksDos = this.baseMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(tailTrucksDos)) {
            res = handlerListAfter(tailTrucksDos);
        }
        return SingleResult.success(res);
    }

    @Override
    public SingleResult fbaOrderSingleJoint(FbaOrderSingleJointReq req, Long userId) {
        FbaOrderOutputDo fbaOrderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(req.getFbaOrderId());
        if (fbaOrderOutputDo.getIsTrucks() == 1) {
            throw new BizException(SysConstant.TailTrucks_JonInit_Error);
        }
        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(req.getTailTrucksId());

        //处理从表信息 以及 更新 first_vessel_order表 is_container状态
        List<Long> orderIdList = new ArrayList<>();
        orderIdList.add(req.getFbaOrderId());
        handlerInsertTailTrucksDetail(orderIdList, tailTrucksDo, 2);

        //更新主表信息
        updateTrucksInfo(req.getTailTrucksId());
        return SingleResult.success();
    }


    private TailTrucksOrderInfo getOrderInfo(List<Long> ids) {
        List<FbaOrderOutputDo> fbaOrderOutputDos = fbaOrderOutputService.getBaseMapper().selectBatchIds(ids);
        int packageCount = 0;
        int productCount = 0;
        double totalVolume = 0;
        double totalWeight = 0;
        Set<Long> companySet = new HashSet<>();
        Set<String> poSet = new HashSet<>();
        for (FbaOrderOutputDo fbaOrderOutputDo : fbaOrderOutputDos) {
            LambdaQueryWrapper<FbaOrderOutputPackageDo> packageDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            packageDoLambdaQueryWrapper.eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, fbaOrderOutputDo.getId());
            List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(packageDoLambdaQueryWrapper);
            companySet.add(fbaOrderOutputDo.getCompanyId());
            if (!CollectionUtils.isEmpty(packageDoList)) {
                for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                    if (StringUtils.isNotBlank(packageDo.getPoNumber())) {
                        poSet.add(packageDo.getPoNumber());
                    }
                    packageCount += packageDo.getCount();
                    totalWeight += packageDo.getWeight() * packageDo.getCount();
                    totalVolume += packageDo.getCount() * packageDo.getLength() * packageDo.getHeight() * packageDo.getWidth() / 1000000;

                    LambdaQueryWrapper<FbaOrderOutputProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    productDoLambdaQueryWrapper.eq(FbaOrderOutputProductDo::getPackageId, packageDo.getId());
                    List<FbaOrderOutputProductDo> orderOutputProductDoList = orderOutputProductDao.selectList(productDoLambdaQueryWrapper);
                    if (!CollectionUtils.isEmpty(orderOutputProductDoList)) {
                        for (FbaOrderOutputProductDo productDo : orderOutputProductDoList) {
                            productCount += productDo.getCount() * packageDo.getCount();
                        }
                    }
                }
            }
        }
        TailTrucksOrderInfo tailTrucksOrderInfo = new TailTrucksOrderInfo();
        tailTrucksOrderInfo.setCompanySet(companySet);
        tailTrucksOrderInfo.setPackageCount(packageCount);
        tailTrucksOrderInfo.setPoSet(poSet);
        tailTrucksOrderInfo.setProductCount(productCount);
        tailTrucksOrderInfo.setTotalVolume(totalVolume);
        tailTrucksOrderInfo.setTotalWeight(totalWeight);
        tailTrucksOrderInfo.setStorageId(fbaOrderOutputDos.get(0).getStorageId());
        tailTrucksOrderInfo.setFbaStorageId(fbaOrderOutputDos.get(0).getFbaStorageId());

        return tailTrucksOrderInfo;
    }

    private void handlerInsertTailTrucksDetail(List<Long> ids, TailTrucksDo tailTrucksDo, Integer type) {
        for (Long id : ids) {
            if (type == 1) {
                FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(id);
                firstVesselOrderDo.setIsContainer(SysConstant.DELETE_FLAG_TRUE);
                firstVesselOrderService.getBaseMapper().updateById(firstVesselOrderDo);
            } else if (type == 2) {
                FbaOrderOutputDo fbaOrderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(id);
                fbaOrderOutputDo.setIsTrucks(SysConstant.DELETE_FLAG_TRUE);
                fbaOrderOutputService.getBaseMapper().updateById(fbaOrderOutputDo);
            }
            TailTrucksDetailDo detailDo = new TailTrucksDetailDo();
            detailDo.setType(type);
            detailDo.setTrucksId(tailTrucksDo.getId());
            detailDo.setOrderId(id);
            detailDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
            tailTrucksDetailDao.insert(detailDo);
        }

    }

    private TailTrucksDo handlerInsertTailTrucksDo(TailTrucksOrderInfo orderInfo, Long templateId, Long userId) {
        TailTrucksDo tailTrucksDo = new TailTrucksDo();
        tailTrucksDo.setProductCount(orderInfo.getProductCount());
        tailTrucksDo.setPackageCount(orderInfo.getPackageCount());
        tailTrucksDo.setTotalVolume(orderInfo.getTotalVolume());
        tailTrucksDo.setTotalWeight(orderInfo.getTotalWeight());
        tailTrucksDo.setTrucksId(templateId);
        tailTrucksDo.setStorageId(orderInfo.getStorageId());
        tailTrucksDo.setFbaStorageId(orderInfo.getFbaStorageId());
        tailTrucksDo.setStatus(1);
        tailTrucksDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        tailTrucksDo.setCreateBy(userId);
        tailTrucksDo.setCreateTime(new Date());
        if (!CollectionUtils.isEmpty(orderInfo.getCompanySet())) {
            List<Long> companyIdList = new ArrayList<>(orderInfo.getCompanySet());
            StringBuilder stringBuilder = new StringBuilder("");
            for (int i = 0; i < companyIdList.size(); i++) {
                CompanyDo companyDo = companyDao.selectById(companyIdList.get(i));
                if (companyDo == null) continue;
                if (i >= companyIdList.size() - 1) {
                    stringBuilder.append(companyDo.getCompanyCode());
                } else {
                    stringBuilder.append(companyDo.getCompanyCode() + ",");
                }
            }
            tailTrucksDo.setTrucksCompanyCode(stringBuilder.toString());
        }
        if (!CollectionUtils.isEmpty(orderInfo.getPoSet())) {
            List<String> poList = new ArrayList<>(orderInfo.getPoSet());
            StringBuilder stringBuilder = new StringBuilder("");
            for (int i = 0; i < poList.size(); i++) {
                if (i >= poList.size() - 1) {
                    stringBuilder.append(poList.get(i));
                } else {
                    stringBuilder.append(poList.get(i) + ",");
                }
            }
            tailTrucksDo.setPoNumberMuti(stringBuilder.toString());
        }
        dao.insert(tailTrucksDo);
        String tailTrucksNumber = OrderCodeUtil.getTailTrucksNumber(tailTrucksDo.getId());
        tailTrucksDo.setTrucksNumber(tailTrucksNumber);
        dao.updateById(tailTrucksDo);

        return tailTrucksDo;
    }

    private void jointCheck(TailTrucksJointFbaReq req) {
        List<FbaOrderOutputDo> fbaOrderOutputDos = fbaOrderOutputService.getBaseMapper().selectBatchIds(req.getIds());
        for (FbaOrderOutputDo fbaOrderOutputDo : fbaOrderOutputDos) {
            if (fbaOrderOutputDo.getIsTrucks() != null && fbaOrderOutputDo.getIsTrucks() == 1) {
                throw new BizException(SysConstant.TailTrucks_JonInit_Error_OrderNo, fbaOrderOutputDo.getFbaOrderOutputNumber());
            }
        }
        Set<Long> storageSet = fbaOrderOutputDos.stream().map(FbaOrderOutputDo::getStorageId).collect(Collectors.toSet());
        Set<Long> fbaStorageSet = fbaOrderOutputDos.stream().map(FbaOrderOutputDo::getFbaStorageId).collect(Collectors.toSet());
        if (fbaStorageSet.size() > 1) {
            throw new BizException(SysConstant.TailTrucks_JoinCheck_Error);
        }
        if (storageSet.size() > 1) {
            if ((storageSet.contains(1L) && storageSet.contains(10L)) || (storageSet.contains(11L) && storageSet.contains(10L)) ||
                    (storageSet.contains(1L) && storageSet.contains(11L))) {

            } else {
                throw new BizException(SysConstant.TailTrucks_JoinCheck_Error);
            }
        }
    }


    private void updateTrucksInfo(Long id) {
        LambdaQueryWrapper<TailTrucksDetailDo> trucksDetailWrapper = new LambdaQueryWrapper<>();
        trucksDetailWrapper.eq(TailTrucksDetailDo::getTrucksId, id);
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(trucksDetailWrapper);
        int packageCount = 0;
        int productCount = 0;
        double totalVolume = 0;
        double totalWeight = 0;
        Set<Long> companyIdSet = new HashSet<>();
        Set<String> poNumberSet = new HashSet<>();

        for (TailTrucksDetailDo tailTrucksDetailDo : tailTrucksDetailDos) {
            if (tailTrucksDetailDo.getType() == 1) {
                FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                companyIdSet.add(firstVesselOrderDo.getCompanyId());
                LambdaQueryWrapper<FirstVesselOrderPackageDo> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(FirstVesselOrderPackageDo::getOrderId, firstVesselOrderDo.getId());
                List<FirstVesselOrderPackageDo> firstVesselOrderPackageDos = firstVesselOrderPackageDao.selectList(wrapper);
                if (!CollectionUtils.isEmpty(firstVesselOrderPackageDos)) {
                    for (FirstVesselOrderPackageDo firstVesselOrderPackageDo : firstVesselOrderPackageDos) {
                        if (StringUtils.isNotBlank(firstVesselOrderPackageDo.getPoNumber())) {
                            poNumberSet.add(firstVesselOrderPackageDo.getPoNumber());
                        }
                        packageCount += firstVesselOrderPackageDo.getCount();
                        totalWeight += firstVesselOrderPackageDo.getWeight() * firstVesselOrderPackageDo.getCount();
                        totalVolume += firstVesselOrderPackageDo.getCount() * firstVesselOrderPackageDo.getLength() * firstVesselOrderPackageDo.getHeight() * firstVesselOrderPackageDo.getWidth() / 1000000;

                        LambdaQueryWrapper<FirstVesselOrderProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        productDoLambdaQueryWrapper.eq(FirstVesselOrderProductDo::getPackageId, firstVesselOrderPackageDo.getId());
                        List<FirstVesselOrderProductDo> firstVesselOrderProductDos = firstVesselOrderProductDao.selectList(productDoLambdaQueryWrapper);
                        if (!CollectionUtils.isEmpty(firstVesselOrderProductDos)) {
                            for (FirstVesselOrderProductDo firstVesselOrderProductDo : firstVesselOrderProductDos) {
                                productCount += firstVesselOrderProductDo.getCount() * firstVesselOrderPackageDo.getCount();
                            }
                        }
                    }
                }
            } else if (tailTrucksDetailDo.getType() == 2) {
                FbaOrderOutputDo orderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                companyIdSet.add(orderOutputDo.getCompanyId());
                LambdaQueryWrapper<FbaOrderOutputPackageDo> packageDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                packageDoLambdaQueryWrapper.eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, orderOutputDo.getId());
                List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(packageDoLambdaQueryWrapper);
                if (!CollectionUtils.isEmpty(packageDoList)) {
                    for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                        if (StringUtils.isNotBlank(packageDo.getPoNumber())) {
                            poNumberSet.add(packageDo.getPoNumber());
                        }
                        packageCount += packageDo.getCount();
                        totalWeight += packageDo.getWeight() * packageDo.getCount();
                        totalVolume += packageDo.getCount() * packageDo.getLength() * packageDo.getHeight() * packageDo.getWidth() / 1000000;

                        LambdaQueryWrapper<FbaOrderOutputProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        productDoLambdaQueryWrapper.eq(FbaOrderOutputProductDo::getPackageId, packageDo.getId());
                        List<FbaOrderOutputProductDo> orderOutputProductDoList = orderOutputProductDao.selectList(productDoLambdaQueryWrapper);
                        if (!CollectionUtils.isEmpty(orderOutputProductDoList)) {
                            for (FbaOrderOutputProductDo productDo : orderOutputProductDoList) {
                                productCount += productDo.getCount() * packageDo.getCount();
                            }
                        }
                    }
                }
            }
        }
        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(id);
        tailTrucksDo.setProductCount(productCount);
        tailTrucksDo.setPackageCount(packageCount);
        tailTrucksDo.setTotalVolume(totalVolume);
        tailTrucksDo.setTotalWeight(totalWeight);
        if (!CollectionUtils.isEmpty(companyIdSet)) {
            List<Long> companyIdList = new ArrayList<>(companyIdSet);
            StringBuilder stringBuilder = new StringBuilder("");
            for (int i = 0; i < companyIdList.size(); i++) {
                CompanyDo companyDo = companyDao.selectById(companyIdList.get(i));
                if (companyDo == null) continue;
                if (i >= companyIdList.size() - 1) {
                    stringBuilder.append(companyDo.getCompanyCode());
                } else {
                    stringBuilder.append(companyDo.getCompanyCode() + ",");
                }
            }
            tailTrucksDo.setTrucksCompanyCode(stringBuilder.toString());
        }
        if (!CollectionUtils.isEmpty(poNumberSet)) {
            List<String> poList = new ArrayList<>(poNumberSet);
            StringBuilder stringBuilder = new StringBuilder("");
            for (int i = 0; i < poList.size(); i++) {
                if (i >= poList.size() - 1) {
                    stringBuilder.append(poList.get(i));
                } else {
                    stringBuilder.append(poList.get(i) + ",");
                }
            }
            tailTrucksDo.setPoNumberMuti(stringBuilder.toString());
        }
        this.baseMapper.updateById(tailTrucksDo);
    }

    private void jointTrucksCheck(TailTrucksJointTrucksReq req) {
        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(req.getId());
        TrucksTemplateDo trucksTemplateDo = trucksTemplateDao.selectById(tailTrucksDo.getTrucksId());


        double volume = 0;
        double weight = 0;

        //将当前选择的订单 加上之前已经拼柜的订单 计算总的体积 和重量 判断是否超标

        //之前已经拼柜的订单
        //头程订单
        LambdaQueryWrapper<TailTrucksDetailDo> trucksDetailVesselWrapper = new LambdaQueryWrapper<>();
        trucksDetailVesselWrapper.eq(TailTrucksDetailDo::getTrucksId, req.getId()).eq(TailTrucksDetailDo::getType, 1);
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(trucksDetailVesselWrapper);
        if (!CollectionUtils.isEmpty(tailTrucksDetailDos)) {
            List<Long> orderIds = tailTrucksDetailDos.stream().map(tailTrucksDetailDo -> {
                return tailTrucksDetailDo.getOrderId();
            }).collect(Collectors.toList());

            LambdaQueryWrapper<FirstVesselOrderPackageDo> packageWrapper = new LambdaQueryWrapper<>();
            packageWrapper.in(FirstVesselOrderPackageDo::getOrderId, orderIds);
            List<FirstVesselOrderPackageDo> firstVesselOrderPackageDos1 = firstVesselOrderPackageDao.selectList(packageWrapper);
            if (!CollectionUtils.isEmpty(firstVesselOrderPackageDos1)) {
                for (FirstVesselOrderPackageDo firstVesselOrderPackageDo : firstVesselOrderPackageDos1) {
                    volume += firstVesselOrderPackageDo.getCount() * firstVesselOrderPackageDo.getLength() * firstVesselOrderPackageDo.getHeight() * firstVesselOrderPackageDo.getWidth() / 1000000;
                    weight += firstVesselOrderPackageDo.getWeight();
                }
            }
        }

        //转运订单
        LambdaQueryWrapper<TailTrucksDetailDo> trucksDetailFbaWrapper = new LambdaQueryWrapper<>();
        trucksDetailFbaWrapper.eq(TailTrucksDetailDo::getTrucksId, req.getId()).eq(TailTrucksDetailDo::getType, 2);
        List<TailTrucksDetailDo> tailTrucksDetailDos1 = tailTrucksDetailDao.selectList(trucksDetailFbaWrapper);
        if (!CollectionUtils.isEmpty(tailTrucksDetailDos1)) {
            List<Long> orderIds = tailTrucksDetailDos1.stream().map(tailTrucksDetailDo -> {
                return tailTrucksDetailDo.getOrderId();
            }).collect(Collectors.toList());

            LambdaQueryWrapper<FbaOrderOutputPackageDo> packageWrapper = new LambdaQueryWrapper<>();
            packageWrapper.in(FbaOrderOutputPackageDo::getFbaOrderOutputId, orderIds);
            List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(packageWrapper);
            if (!CollectionUtils.isEmpty(packageDoList)) {
                for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                    volume += packageDo.getCount() * packageDo.getLength() * packageDo.getHeight() * packageDo.getWidth() / 1000000;
                    weight += packageDo.getWeight();
                }
            }
        }


        //当前选择的订单

        if (req.getType() == 1) {
            LambdaQueryWrapper<FirstVesselOrderPackageDo> packageWrapper = new LambdaQueryWrapper<>();
            packageWrapper.in(FirstVesselOrderPackageDo::getOrderId, req.getOrderIds());
            List<FirstVesselOrderPackageDo> firstVesselOrderPackageDos = firstVesselOrderPackageDao.selectList(packageWrapper);

            if (!CollectionUtils.isEmpty(firstVesselOrderPackageDos)) {
                for (FirstVesselOrderPackageDo firstVesselOrderPackageDo : firstVesselOrderPackageDos) {
                    volume += firstVesselOrderPackageDo.getCount() * firstVesselOrderPackageDo.getLength() * firstVesselOrderPackageDo.getHeight() * firstVesselOrderPackageDo.getWidth() / 1000000;
                    weight += firstVesselOrderPackageDo.getWeight();
                }
            }
        } else if (req.getType() == 2) {
            LambdaQueryWrapper<FbaOrderOutputPackageDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(FbaOrderOutputPackageDo::getFbaOrderOutputId, req.getOrderIds());
            List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(wrapper);
            if (!CollectionUtils.isEmpty(packageDoList)) {
                for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                    volume += packageDo.getCount() * packageDo.getLength() * packageDo.getHeight() * packageDo.getWidth() / 1000000;
                    weight += packageDo.getWeight();
                }
            }
        }


        if (trucksTemplateDo.getVolume() < volume || trucksTemplateDo.getWeight() < weight) {
            throw new BizException(SysConstant.TailTrucks_OverSize);
        }

        //验证订单是否已经存在
        for (Long orderId : req.getOrderIds()) {
            LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TailTrucksDetailDo::getOrderId, orderId).eq(TailTrucksDetailDo::getType, req.getType());
            int integer = tailTrucksDetailDao.selectCount(wrapper);
            if (integer > 0) {
                if (req.getType() == 1) {
                    FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(orderId);
                    throw new BizException(SysConstant.TailTrucks_Check_Error1, firstVesselOrderDo.getOrderNumber());
                } else if (req.getType() == 2) {
                    FbaOrderOutputDo orderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(orderId);
                    throw new BizException(SysConstant.TailTrucks_Check_Error2, orderOutputDo.getFbaOrderOutputNumber());
                }
            }
        }

    }


    @Override
    public SingleResult updateInit(Long id) {
        return SingleResult.success("");
    }

    @Override
    public Object update(Object req, Long userId) {
        /*TailTrucksDo entityDo = dao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return handlerUpdateAfter(entityDo);*/
        return null;
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(TailTrucksDo entityDo, Long userId) {
    }

    //做修改之后要执行的业务定制处理
    private Object handlerUpdateAfter(TailTrucksDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public int delete(Long id, Long userId) {
        dao.deleteById(id);

        LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TailTrucksDetailDo::getTrucksId, id);
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(wrapper);

        if (!CollectionUtils.isEmpty(tailTrucksDetailDos)) {
            tailTrucksDetailDos.forEach(tailTrucksDetailDo -> {
                if (tailTrucksDetailDo.getType() == 1) {
                    FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                    if (firstVesselOrderDo != null) {
                        firstVesselOrderDo.setIsContainer(SysConstant.DELETE_FLAG_FALSE);
                        firstVesselOrderService.getBaseMapper().updateById(firstVesselOrderDo);
                    }
                } else if (tailTrucksDetailDo.getType() == 2) {
                    FbaOrderOutputDo orderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                    if (orderOutputDo != null) {
                        orderOutputDo.setIsTrucks(SysConstant.DELETE_FLAG_FALSE);
                        fbaOrderOutputService.getBaseMapper().updateById(orderOutputDo);
                    }
                }
            });
        }

        tailTrucksDetailDao.delete(wrapper);
        return 1;
    }

    @Override
    public void updatePoNumberHandler(Long id) {
        LambdaQueryWrapper<TailTrucksDetailDo> detailWrapper = new LambdaQueryWrapper<>();
        detailWrapper.eq(TailTrucksDetailDo::getTrucksId, id);
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(detailWrapper);
        Set<Long> companyIds = new HashSet<>();
        Set<String> poSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(tailTrucksDetailDos)) {
            for (TailTrucksDetailDo tailTrucksDetailDo : tailTrucksDetailDos) {
                if (tailTrucksDetailDo.getType() == 1) {
                    FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                    companyIds.add(firstVesselOrderDo.getCompanyId());
                    LambdaQueryWrapper<FirstVesselOrderPackageDo> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(FirstVesselOrderPackageDo::getOrderId, firstVesselOrderDo.getId());
                    List<FirstVesselOrderPackageDo> firstVesselOrderPackageDos = firstVesselOrderPackageDao.selectList(wrapper);
                    if (!CollectionUtils.isEmpty(firstVesselOrderPackageDos)) {
                        for (FirstVesselOrderPackageDo firstVesselOrderPackageDo : firstVesselOrderPackageDos) {
                            poSet.add(firstVesselOrderPackageDo.getPoNumber());
                        }
                    }
                } else if (tailTrucksDetailDo.getType() == 2) {
                    FbaOrderOutputDo orderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                    companyIds.add(orderOutputDo.getCompanyId());
                    LambdaQueryWrapper<FbaOrderOutputPackageDo> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, orderOutputDo.getId());
                    List<FbaOrderOutputPackageDo> fbaOrderOutputPackageDos = orderOutputPackageDao.selectList(wrapper);
                    if (!CollectionUtils.isEmpty(fbaOrderOutputPackageDos)) {
                        for (FbaOrderOutputPackageDo fbaOrderOutputPackageDo : fbaOrderOutputPackageDos) {
                            poSet.add(fbaOrderOutputPackageDo.getPoNumber());
                        }
                    }
                }
            }
        }


        TailTrucksDo tailTrucksDo = this.baseMapper.selectById(id);
        if (!CollectionUtils.isEmpty(companyIds)) {
            List<Long> companyIdList = new ArrayList<>(companyIds);
            StringBuilder stringBuilder = new StringBuilder("");
            for (int i = 0; i < companyIdList.size(); i++) {
                CompanyDo companyDo = companyDao.selectById(companyIdList.get(i));
                if (companyDo == null) continue;
                if (i >= companyIdList.size() - 1) {
                    stringBuilder.append(companyDo.getCompanyCode());
                } else {
                    stringBuilder.append(companyDo.getCompanyCode() + ",");
                }
            }
            tailTrucksDo.setTrucksCompanyCode(stringBuilder.toString());
        }
        if (!CollectionUtils.isEmpty(poSet)) {
            List<String> poList = new ArrayList<>(poSet);
            StringBuilder stringBuilder = new StringBuilder("");
            for (int i = 0; i < poList.size(); i++) {
                if (i >= poList.size() - 1) {
                    stringBuilder.append(poList.get(i));
                } else {
                    stringBuilder.append(poList.get(i) + ",");
                }
            }
            tailTrucksDo.setPoNumberMuti(stringBuilder.toString());
        }
        this.baseMapper.updateById(tailTrucksDo);
    }

    @Override
    public int deleteOrder(TailTrucksDeleteReq req) {

        LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TailTrucksDetailDo::getTrucksId, req.getId()).eq(TailTrucksDetailDo::getOrderId, req.getOrderId()).eq(TailTrucksDetailDo::getType, req.getType());
        tailTrucksDetailDao.delete(wrapper);

        if (req.getType() == 1) {
            FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(req.getOrderId());
            if (firstVesselOrderDo != null) {
                firstVesselOrderDo.setIsContainer(SysConstant.DELETE_FLAG_FALSE);
                firstVesselOrderService.getBaseMapper().updateById(firstVesselOrderDo);
            }
        } else if (req.getType() == 2) {
            FbaOrderOutputDo orderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(req.getOrderId());
            if (orderOutputDo != null) {
                orderOutputDo.setIsTrucks(SysConstant.DELETE_FLAG_FALSE);
                fbaOrderOutputService.getBaseMapper().updateById(orderOutputDo);
            }
        }

        updateTrucksInfo(req.getId());
        return 0;
    }


    @Override
    public List<TailTrucksDetailListRes> detail(Long id) {
        List<TailTrucksDetailListRes> resList = new ArrayList<>();

        LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TailTrucksDetailDo::getTrucksId, id);
        List<TailTrucksDetailDo> tailTrucksDetailDos = tailTrucksDetailDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(tailTrucksDetailDos)) {
            for (TailTrucksDetailDo tailTrucksDetailDo : tailTrucksDetailDos) {
                TailTrucksDetailListRes res = new TailTrucksDetailListRes();
                if (tailTrucksDetailDo.getType() == 1) {
                    res.setType(1);
                    FirstVesselOrderDo firstVesselOrderDo = firstVesselOrderService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                    if (firstVesselOrderDo == null) continue;
                    res.setId(firstVesselOrderDo.getId());
                    res.setOrderNumber(firstVesselOrderDo.getOrderNumber());
                    CompanyDo companyDo = companyDao.selectById(firstVesselOrderDo.getCompanyId());
                    if (companyDo != null) {
                        res.setCompanyCode(companyDo.getCompanyCode());
                    }
                    FbaStorageDo fbaStorageDo = fbaStorageDao.selectById(firstVesselOrderDo.getFbaStorageId());
                    if (fbaStorageDo != null) {
                        res.setFbaStorage(fbaStorageDo.getFbaCode());
                    }
                    DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(firstVesselOrderDo.getStatus());
                    if (businessItemDo != null) {
                        res.setStatus(businessItemDo.getDicItemValue());
                    }

                    LambdaQueryWrapper<FirstVesselOrderPackageDo> packageDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    packageDoLambdaQueryWrapper.eq(FirstVesselOrderPackageDo::getOrderId, firstVesselOrderDo.getId());
                    List<FirstVesselOrderPackageDo> packageDoList = firstVesselOrderPackageDao.selectList(packageDoLambdaQueryWrapper);

                    int packageCount = packageDoList.stream().mapToInt(FirstVesselOrderPackageDo::getCount).sum();
                    double totalWeight = 0;
                    double totalVolume = 0;
                    int productCount = 0;

                    res.setPackageCount(packageCount);
                    if (!CollectionUtils.isEmpty(packageDoList)) {
                        for (FirstVesselOrderPackageDo packageDo : packageDoList) {
                            totalVolume += packageDo.getHeight() * packageDo.getLength() * packageDo.getWidth() * packageDo.getCount();
                            totalWeight += packageDo.getCount() * packageDo.getWeight();
                            LambdaQueryWrapper<FirstVesselOrderProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                            productDoLambdaQueryWrapper.eq(FirstVesselOrderProductDo::getPackageId, packageDo.getId());
                            List<FirstVesselOrderProductDo> firstVesselOrderProductDos = firstVesselOrderProductDao.selectList(productDoLambdaQueryWrapper);
                            if (!CollectionUtils.isEmpty(firstVesselOrderProductDos)) {
                                productCount += firstVesselOrderProductDos.stream().mapToInt(FirstVesselOrderProductDo::getCount).sum() * packageDo.getCount();
                            }
                        }
                    }
                    res.setWeight(totalWeight);
                    res.setVolume(numberFormat(totalVolume));
                    res.setProductCount(productCount);

                    resList.add(res);
                } else if (tailTrucksDetailDo.getType() == 2) {
                    res.setType(2);
                    FbaOrderOutputDo orderOutputDo = fbaOrderOutputService.getBaseMapper().selectById(tailTrucksDetailDo.getOrderId());
                    if (orderOutputDo == null) continue;
                    res.setId(orderOutputDo.getId());
                    res.setOrderNumber(orderOutputDo.getFbaOrderOutputNumber());

                    Set<String> poSet = new HashSet<>();
                    LambdaQueryWrapper<FbaOrderOutputPackageDo> packageWrapper = new LambdaQueryWrapper<>();
                    packageWrapper.eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, orderOutputDo.getId());
                    List<FbaOrderOutputPackageDo> fbaOrderOutputPackageDos = orderOutputPackageDao.selectList(packageWrapper);
                    if (!CollectionUtils.isEmpty(fbaOrderOutputPackageDos)) {
                        for (FbaOrderOutputPackageDo packageDo : fbaOrderOutputPackageDos) {
                            poSet.add(packageDo.getPoNumber());
                        }
                    }
                    if (!CollectionUtils.isEmpty(poSet)) {
                        List<String> poList = new ArrayList<>(poSet);
                        StringBuilder stringBuilder = new StringBuilder("");
                        for (int i = 0; i < poList.size(); i++) {
                            if (i >= poList.size() - 1) {
                                stringBuilder.append(poList.get(i));
                            } else {
                                stringBuilder.append(poList.get(i) + ",");
                            }
                        }
                        res.setPoNumber(stringBuilder.toString());
                    }


                    CompanyDo companyDo = companyDao.selectById(orderOutputDo.getCompanyId());
                    if (companyDo != null) {
                        res.setCompanyCode(companyDo.getCompanyCode());
                    }
                    FbaStorageDo fbaStorageDo = fbaStorageDao.selectById(orderOutputDo.getFbaStorageId());
                    if (fbaStorageDo != null) {
                        res.setFbaStorage(fbaStorageDo.getFbaCode());
                    }
                    StorageDo storageDo = storageService.getBaseMapper().selectById(orderOutputDo.getStorageId());
                    if (storageDo != null) {
                        res.setStorage(storageDo.getStorageName());
                    }
                    DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(orderOutputDo.getStatus());
                    if (businessItemDo != null) {
                        res.setStatus(businessItemDo.getDicItemValue());
                    }
                    LambdaQueryWrapper<FbaOrderOutputPackageDo> packageDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    packageDoLambdaQueryWrapper.eq(FbaOrderOutputPackageDo::getFbaOrderOutputId, orderOutputDo.getId());
                    List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(packageDoLambdaQueryWrapper);

                    int packageCount = packageDoList.stream().mapToInt(FbaOrderOutputPackageDo::getCount).sum();
                    double totalWeight = 0;
                    double totalVolume = 0;
                    int productCount = 0;

                    res.setPackageCount(packageCount);

                    if (!CollectionUtils.isEmpty(packageDoList)) {
                        for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                            totalVolume += packageDo.getHeight() * packageDo.getLength() * packageDo.getWidth() * packageDo.getCount() / 1000000;
                            totalWeight += packageDo.getCount() * packageDo.getWeight();
                            LambdaQueryWrapper<FbaOrderOutputProductDo> productDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                            productDoLambdaQueryWrapper.eq(FbaOrderOutputProductDo::getPackageId, packageDo.getId());
                            List<FbaOrderOutputProductDo> orderOutputProductDoList = orderOutputProductDao.selectList(productDoLambdaQueryWrapper);
                            if (!CollectionUtils.isEmpty(orderOutputProductDoList)) {
                                productCount += orderOutputProductDoList.stream().mapToInt(FbaOrderOutputProductDo::getCount).sum() * packageDo.getCount();
                            }
                        }
                    }
                    res.setWeight(numberFormat(totalWeight));
                    res.setVolume(numberFormat(totalVolume));
                    res.setProductCount(productCount);

                    resList.add(res);
                }
            }
        }
        //编辑拼柜的po号
        executor.execute(() -> {
            if (!CollectionUtils.isEmpty(tailTrucksDetailDos)) {
                updatePoNumberHandler(tailTrucksDetailDos.get(0).getTrucksId());
            }
        });
        return resList;
    }


    @Override
    public SingleResult pageInit(Long companyId, Long userId) {
        Map map = new HashMap();
        List<StorageListRes> list = storageService.getList(new HashMap<>());
        map.put("storageList", list);
        List<Long> ids = new ArrayList<>();
        LambdaQueryWrapper<TrucksTemplateDo> wrapper = new LambdaQueryWrapper<>();
        List<TrucksTemplateDo> trackCompanyList = trucksTemplateDao.selectList(wrapper);
        List<IdAndNameEntity> trackList = new ArrayList<>();
        for (TrucksTemplateDo itemDo : trackCompanyList) {
            StorageDo storageDo = storageService.getById(itemDo.getStorageId());
            trackList.add(new IdAndNameEntity(itemDo.getId().intValue(),
                    itemDo.getTrucksCode() + (storageDo == null ? "" : String.format("(%s)", storageDo.getCode()))));
        }
        map.put("truckList", trackList);
        List<Map> shopList = shopService.selectShopListInit(userId, companyId);
        List<Map> companyList = companyService.getInitList(companyId);
        map.put("companyList", companyList);
        //fbaStorage
        QueryWrapper wrapper1 = new QueryWrapper();
        wrapper1.orderByAsc("fba_code");
        List<FbaStorageDo> fbaStorageDos = fbaStorageDao.selectList(wrapper1);
        List<Map> fbaStorageList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fbaStorageDos)) {
            fbaStorageDos.forEach(fbaStorageDo -> {
                Map fbaMap = new HashMap();
                fbaMap.put("id", fbaStorageDo.getId());
                fbaMap.put("value", fbaStorageDo.getFbaCode());
                fbaStorageList.add(fbaMap);
            });
        }
        map.put("fbaStorageList", fbaStorageList);

        return SingleResult.success(map);
    }


    @Override
    public List<TailTrucksPageRes> getList(Map<String, String> map) {
        QueryWrapper<TailTrucksDo> wrapper = queryBuild(map);
        List<TailTrucksDo> list = this.list(wrapper);
        List<TailTrucksPageRes> result = handlerListAfter(list);
        return result;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<TailTrucksDo> wrapper = queryBuild(map);
        IPage<TailTrucksDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<TailTrucksPageRes> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        result.setMapInfo(getStatusList(map));
        return result;
    }


    private Map getStatusList(Map<String, String> wrapper) {
        List<LanguageCountEntity> mapList = new ArrayList<>();
        wrapper.put("status", null);
        List<TailTrucksDo> list = dao.selectList(queryBuild(wrapper));
        Map<Integer, List<TailTrucksDo>> listMap = list.stream().collect(Collectors.groupingBy(TailTrucksDo::getStatus));
        mapList.add(new LanguageCountEntity(null, "全部", list.size()));
        mapList.add(new LanguageCountEntity(1, "待确定", listMap.get(1) == null ? 0 : listMap.get(1).size()));
        mapList.add(new LanguageCountEntity(5, "待回复", listMap.get(5) == null ? 0 : listMap.get(5).size()));
        mapList.add(new LanguageCountEntity(2, "待约车", listMap.get(2) == null ? 0 : listMap.get(2).size()));
        mapList.add(new LanguageCountEntity(3, "已约车", listMap.get(3) == null ? 0 : listMap.get(3).size()));
        mapList.add(new LanguageCountEntity(4, "已配送", listMap.get(4) == null ? 0 : listMap.get(4).size()));

        Map result = new HashMap();
        result.put("statusList", mapList);
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<TailTrucksPageRes> handlerListAfter(List<TailTrucksDo> list) {
        List<TailTrucksPageRes> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(tailTrucksDo -> {
                TailTrucksPageRes res = new TailTrucksPageRes();
                BeanUtils.copyProperties(tailTrucksDo, res);
                TrucksTemplateDo trucksTemplateDo = trucksTemplateDao.selectById(tailTrucksDo.getTrucksId());
                if (trucksTemplateDo != null) {
                    res.setTrucks(trucksTemplateDo.getTrucksCode());
                    res.setTruckVolume(trucksTemplateDo.getVolume());
                    res.setTruckWeight(trucksTemplateDo.getWeight());
                }
                res.setStatusId(tailTrucksDo.getStatus());
                res.setStatus(getStatusStr(tailTrucksDo.getStatus()));
                FbaStorageDo fbaStorageDo = fbaStorageDao.selectById(tailTrucksDo.getFbaStorageId());
                if (fbaStorageDo != null) {
                    res.setFbaStorage(fbaStorageDo.getFbaCode());
                }
                StorageDo storageDo = storageService.getBaseMapper().selectById(tailTrucksDo.getStorageId());
                if (storageDo != null) {
                    res.setStorage(storageDo.getCode());
                }
                List<TailTrucksDetailListRes> detail = detail(tailTrucksDo.getId());
                res.setItems(detail);
                result.add(res);
            });
        }
        return result;
    }

    private String getStatusStr(Integer status) {
        if (status == 1) {
            return "待确定";
        } else if (status == 2) {
            return "待约车";
        } else if (status == 3) {
            return "已约车";
        } else if (status == 4) {
            return "已配送";
        }
        return "";
    }

    private IPage<TailTrucksDo> pageInit(Map<String, String> map) {
        IPage<TailTrucksDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<TailTrucksDo> queryBuild(Map<String, String> map) {
        QueryWrapper<TailTrucksDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.or(tailTrucksDoQueryWrapper -> {
                tailTrucksDoQueryWrapper.like("trucks_number", map.get("keyword")).or().
                        like("po_number_muti", map.get("keyword")
                        ).or().like("appointment_code", map.get("keyword")
                        ).or().like("appointment_code2", map.get("keyword")
                        ).or().like("appointment_code3", map.get("keyword"));
            });
        }
        if (StringUtils.isNotBlank(map.get("status"))) {
            wrapper.eq("status", map.get("status"));
        }
        if (StringUtils.isNotBlank(map.get("fbaStorageId"))) {
            wrapper.eq("fba_storage_id", map.get("fbaStorageId"));
        }
        if (StringUtils.isNotBlank(map.get("storageId"))) {
            wrapper.eq("storage_id", map.get("storageId"));
        }
        if (StringUtils.isNotBlank(map.get("truckId"))) {
            wrapper.eq("truck_id", map.get("truckId"));
        }
        if (StringUtils.isNotBlank(map.get("companyCode"))) {
            wrapper.like("trucks_company_code", map.get("companyCode"));
        }
        if (StringUtils.isNotBlank(map.get("startDate"))) {
            wrapper.ge("create_time", map.get("startDate"));
        }
        if (StringUtils.isNotBlank(map.get("endDate"))) {
            wrapper.le("create_time", map.get("endDate"));
        }
        return wrapper.orderByDesc("id");
    }

    @Override
    public void exportAmazonReceivePage(Long id, HttpServletResponse response) {
        List<TailTrucksAmazonPagePackageVo> amazonPagePackageVos = new ArrayList<>();
        TailTrucksAmazonPageAddressInfoVo pageAddressInfoVo = new TailTrucksAmazonPageAddressInfoVo();
        List<FbaOrderOutputDo> firstVesselOrderDoList = new ArrayList<>();
        List<Long> orderOrigionOrderIds = new ArrayList<>();
        TailTrucksDo tailTrucksDo = dao.selectById(id);
        if (tailTrucksDo != null) {
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("trucks_id", id);
            List<TailTrucksDetailDo> trucksDetailDoList = tailTrucksDetailDao.selectList(wrapper);
            if (trucksDetailDoList.size() < 1) return;
            for (TailTrucksDetailDo headerContainerOrderDo : trucksDetailDoList) {
                orderOrigionOrderIds.add(headerContainerOrderDo.getOrderId());
            }
            firstVesselOrderDoList = orderOutputDao.selectBatchIds(orderOrigionOrderIds);
        } else {
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("order_id", id);
            List<TailTrucksDetailDo> trucksDetailDoList = tailTrucksDetailDao.selectList(wrapper);
            if (trucksDetailDoList.size() > 0) {
                for (TailTrucksDetailDo headerContainerOrderDo : trucksDetailDoList) {
                    orderOrigionOrderIds.add(headerContainerOrderDo.getOrderId());
                }
                Long trailId = trucksDetailDoList.get(0).getTrucksId();
                tailTrucksDo = dao.selectById(trailId);
            }
            if (tailTrucksDo == null) {
                FbaOrderOutputDo orderOutputDo = orderOutputDao.selectById(id);
                firstVesselOrderDoList.add(orderOutputDo);
                tailTrucksDo = new TailTrucksDo();
                tailTrucksDo.setAmazonTime(orderOutputDo.getAppointmentStorageTime());
            } else {
                firstVesselOrderDoList = orderOutputDao.selectBatchIds(orderOrigionOrderIds);
            }
        }

//        List<OrderOutputDo> firstVesselOrderDoList = new ArrayList<>();
//        firstVesselOrderDoList.add(orderOutputDao.selectById(65L));
        int index = 0;
        int totalCount = 0;
        int packageTotalCount = 0;
        for (FbaOrderOutputDo orderDo :
                firstVesselOrderDoList) {
            pageAddressInfoVo.setFbaId(tailTrucksDo.getAppointmentCode());
            if (tailTrucksDo.getAmazonTime() != null)
                pageAddressInfoVo.setTime(TimeUtils.formatDate(tailTrucksDo.getAmazonTime(), "yyyy-MM-dd HH:mm"));
            FbaStorageDo fbaStorageDo = fbaStorageDao.selectById(orderDo.getFbaStorageId());
            if (fbaStorageDo != null) {
                pageAddressInfoVo.setFbaAddress((StringUtils.isNotBlank(fbaStorageDo.getPostCode()) ? "〒" + fbaStorageDo.getPostCode() : "") +
                        fbaStorageDo.getAddress());
                pageAddressInfoVo.setFbaName(fbaStorageDo.getFbaCode() + fbaStorageDo.getFbaName());
                pageAddressInfoVo.setFbaPhone(fbaStorageDo.getTelPhone());
            }
            StorageDo storageDo = storageDao.selectById(orderDo.getStorageId());
            pageAddressInfoVo.setStorageAddress(storageDo.getAddress());
//            pageAddressInfoVo.setStoragePhone(storageDo.get());
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("fba_order_output_id", orderDo.getId());
            List<FbaOrderOutputPackageDo> packageDoList = orderOutputPackageDao.selectList(wrapper);
            if (packageDoList.size() < 1) {
                throw new BizException(SysConstant.OrderInput_Package_NotExist);
            }
            for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                TailTrucksAmazonPagePackageVo pagePackageVo = new TailTrucksAmazonPagePackageVo();
                pagePackageVo.setCompanyCode(companyDao.selectById(orderDo.getCompanyId()).getCompanyCode());
                pagePackageVo.setPo(packageDo.getPoNumber());
                pagePackageVo.setPackageCount(packageDo.getCount());
                wrapper = new QueryWrapper();
                wrapper.eq("package_id", packageDo.getId());
                List<FbaOrderOutputProductDo> productDoList = orderOutputProductDao.selectList(wrapper);
                if (packageDoList.size() > 0) {
                    for (FbaOrderOutputProductDo productDo : productDoList) {
                        ProductInfoDo productInfoDo = productInfoDao.selectById(productDo.getProductId());
                        if (productInfoDo != null) {
                            pagePackageVo.setCommoditySku(productInfoDo.getCommoditySku());
                        }
                        index++;
                        pagePackageVo.setTotalCount(packageDo.getCount() * productDo.getCount());
                        pagePackageVo.setCount(productDo.getCount());
                        pagePackageVo.setIndex(index);
                        amazonPagePackageVos.add(pagePackageVo);
                    }
                } else {
                    index++;
                    pagePackageVo.setTotalCount(packageDo.getCount());
                    pagePackageVo.setIndex(index);
                    amazonPagePackageVos.add(pagePackageVo);
                }
                totalCount = totalCount + pagePackageVo.getTotalCount();
                packageTotalCount = packageTotalCount + pagePackageVo.getPackageCount();
            }
        }
        pageAddressInfoVo.setPackageTotalCount(packageTotalCount);
        pageAddressInfoVo.setTotalCount(totalCount);
        // 获取模板文件路径
        TemplateExportParams params = new TemplateExportParams(templatePath + "FBA受領書.xls", true);
        //设置sheetName，若不设置该参数，则使用得原本得sheet名称
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("list1", amazonPagePackageVos);
        data.put("storage", pageAddressInfoVo);
        ImageEntity imageEntity = new ImageEntity();
        String orderNo;
        if (firstVesselOrderDoList.size() == 1) {
            orderNo = firstVesselOrderDoList.get(0).getFbaOrderOutputNumber();
        } else {
            orderNo = tailTrucksDo.getTrucksNumber();
        }
        imageEntity.setUrl(BarCodeUtils.createCodeImage(orderNo, filePathLocal, orderNo + ".png"));
        imageEntity.setColspan(3);
        imageEntity.setRowspan(2);
        data.put("imageCode", imageEntity);

        // 获取workbook
        Workbook workbook = ExcelExportUtil.exportExcel(params, data);
        try {
            ExcelUtils.downLoadExcel("FBA受領書", response, workbook);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportPickupPage(Long id, HttpServletResponse response) {
        List<Long> ids = new ArrayList<>();
        TailTrucksDo entityDo = this.baseMapper.selectById(id);
        if (entityDo != null) {
            LambdaQueryWrapper<TailTrucksDetailDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TailTrucksDetailDo::getTrucksId, entityDo.getId());
            List<TailTrucksDetailDo> detailDoList = tailTrucksDetailDao.selectList(wrapper);
            if (detailDoList != null) {
                detailDoList.stream().forEach(detailDo -> {
                    ids.add(detailDo.getOrderId());
                });
            }
        } else {
            ids.add(id);
        }
        List<FbaOrderOutputDo> orderOutputDoList = new ArrayList<>();
        if (ids != null && ids.size() > 0) {
            orderOutputDoList = this.fbaOrderOutputDao.selectBatchIds(ids);
        } else {
//            orderOutputDoList = this.baseMapper.selectList(wrapper);
        }
        List<FbaOrderOutputCommonExportVo> excelExportVoList = new ArrayList<>();

        orderOutputDoList.stream()
                .forEach(orderOutputDo -> {
                    StringBuilder stringBuilder = new StringBuilder();
                    QueryWrapper wrapper1 = new QueryWrapper();
                    FbaOrderOutputCommonExportVo exportVo = new FbaOrderOutputCommonExportVo();
//                    exportVo.setSendDate(TimeUtils.formatDate(orderOutputDo.getSendDate(), "yy月dd日"));
//                    exportVo.setOrderNo(orderOutputDo.getOrderNo());
                    exportVo.setStorage(storageDao.selectById(orderOutputDo.getStorageId()).getCode());
                    exportVo.setFbaStorage(fbaStorageDao.selectById(orderOutputDo.getFbaStorageId()).getFbaCode());
//                    exportVo.setCompanyCode(companyDao.selectById(orderOutputDo.getCompanyId()).getCompanyCode());
                    wrapper1.eq("fba_order_output_id", orderOutputDo.getId());
                    List<FbaOrderOutputPackageDo> packageDoList = fbaOrderOutputPackageDao.selectList(wrapper1);
                    List<FbaOrderOutputCommonPackageExportVo> packageExportVoList = new ArrayList<>();
                    int i = 1;
                    for (FbaOrderOutputPackageDo packageDo : packageDoList) {
                        FbaOrderOutputCommonPackageExportVo packageExportVo = new FbaOrderOutputCommonPackageExportVo();
                        BeanUtils.copyProperties(packageDo, packageExportVo);
                        packageExportVo.setPackageCount(packageDo.getCount());
//                        packageExportVo.setPackageNumber(i + "-" + (i + packageDo.getCount() - 1));
                        i = i + packageDo.getCount();
                        wrapper1 = new QueryWrapper();
                        wrapper1.eq("package_id", packageDo.getId());
                        List<FbaOrderOutputProductDo> productDoList = fbaOrderOutputProductDao.selectList(wrapper1);
                        List<FbaOrderOutputCommonProductExportVo> productExcelExportVoList = new ArrayList<>();
                        if (productDoList.size() > 0) {
                            for (FbaOrderOutputProductDo product : productDoList) {
                                FbaOrderOutputCommonProductExportVo productExportVo = new FbaOrderOutputCommonProductExportVo();
                                ProductInfoDo productInfoDo = productInfoDao.selectById(product.getProductId());
                                productExportVo.setCount(product.getCount());
                                productExportVo.setCommoditySku(productInfoDo.getCommoditySku());
                                productExportVo.setStorageSku(productInfoDo.getStorageSku());
//                                productExportVo.setTotalCount(product.getCount() * packageDo.getCount());
                                productExcelExportVoList.add(productExportVo);
                            }
                        } else {
                            FbaOrderOutputCommonProductExportVo productExportVo = new FbaOrderOutputCommonProductExportVo();
//                            productExportVo.setTotalCount(packageDo.getCount());
                            productExcelExportVoList.add(productExportVo);
                        }
                        if (stringBuilder.length() > 1)
                            stringBuilder.append(",");
                        stringBuilder.append(packageDo.getPoNumber());
                        packageExportVo.setProductExportVoList(productExcelExportVoList);
                        packageExportVoList.add(packageExportVo);
                    }
                    exportVo.setPackageExportVoList(packageExportVoList);
//                            exportVo.setPoNumber(stringBuilder.toString());
                    int count = fbaOrderOutputPackageDao.selectCountByOrderId(orderOutputDo.getId());
                    exportVo.setTotalCount(count);
                    excelExportVoList.add(exportVo);
                });
        try {
            ExportParams exportParams = new ExportParams();
            exportParams.setStyle(ExcelExportStylerBorderImpl.class);
            ExcelUtils.exportExcel(excelExportVoList, FbaOrderOutputCommonExportVo.class, TimeUtils.getCurrentDateFormat() + "出荷依頼.xls", exportParams, response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private double numberFormat(double f) {
        BigDecimal b = new BigDecimal(f);
        return b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    /**
     * 修改预约时间
     */
    @Override
    public void updateAmazonTime(UpdateAmazonTimeReq req) {
        //前端没有传 默认传 ""
        if ("".equals(req.getAmazonTime()) && "".equals(req.getAmazonTime2()) && "".equals(req.getAmazonTime3())) {
            throw new BizException(SysConstant.TailTrucks_Fill_Time);
        }

        TailTrucksDo tailTrucksDo = dao.selectById(req.getId());
        if (tailTrucksDo == null) {
            throw new BizException(SysConstant.Error_Data_NotExist);
        }
        if (tailTrucksDo.getStatus() == 4) {
            throw new BizException(SysConstant.TailTrucks_Update_HadSend);
        }

        LambdaUpdateWrapper<TailTrucksDo> updateWrapper = new LambdaUpdateWrapper<>();

        if (!"".equals(req.getAmazonTime())) {
            if (StringUtils.isBlank(tailTrucksDo.getAppointmentCode())) {
                throw new BizException(SysConstant.TailTrucks_Code1_Error);
            }
            updateWrapper.set(TailTrucksDo::getAmazonTime, req.getAmazonTime());
            updateWrapper.set(TailTrucksDo::getTimeStatus, "normal");
        }
        if (!"".equals(req.getAmazonTime2())) {
            if (StringUtils.isBlank(tailTrucksDo.getAppointmentCode2())) {
                throw new BizException(SysConstant.TailTrucks_Code2_Error);
            }
            updateWrapper.set(TailTrucksDo::getAmazonTime2, req.getAmazonTime2());
            updateWrapper.set(TailTrucksDo::getTimeStatus2, "normal");
        }

        if (!"".equals(req.getAmazonTime3())) {
            if (StringUtils.isBlank(tailTrucksDo.getAppointmentCode3())) {
                throw new BizException(SysConstant.TailTrucks_Code3_Error);
            }
            updateWrapper.set(TailTrucksDo::getAmazonTime3, req.getAmazonTime3());
            updateWrapper.set(TailTrucksDo::getTimeStatus3, "normal");
        }

        //只有待回复状态 修改亚马逊时间 才变成待约车
        if (tailTrucksDo.getStatus() == 5) {
            updateWrapper.set(TailTrucksDo::getStatus, 2);
        }
        updateWrapper.eq(TailTrucksDo::getId, req.getId());
        this.update(updateWrapper);
    }
}
